import copy
from grammar import getAllSymble
# 状态类
class Status:
    # 传入文法集合，左部-文法映射
    def __init__(self,gras,graMap):
        # 文法集合
        self._gras = copy.deepcopy(gras); 
        # 检查
        check = True
        while check:
            # 假设结束
            check = False
            # 遍历状态中每一个文法
            grasList = list(self._gras)
            
            for gra in grasList:
                # print('当前文法为%s'%gra)
                # 得到当前文法的方向
                curSym = gra.getCurDire()
                # # 如果这个文法已经clouser过了，继续
                if curSym == None:
                    continue
                # closed.add(curSym)
                # 如果是非终结符
                if(curSym[0] == '<'):
                    # 遍历所有以该非终结符为左部的文法
                    for g in graMap[curSym]:
                        if not g in self._gras:
                            # 加入这个文法
                            self._gras.add(g)
                            # 继续检查
                            check = True



    # 返回可以前进的方向列表
    def getDire(self):
        dirs = set()
        for gra in self._gras:
            dire = gra.getCurDire()
            # 可以规约就不要添加了
            if dire != None:
                dirs.add(dire)
        return list(dirs)

    # 向指定的方向前进并返回新的状态
    def forward(self,dire,graMap):

        gramSet = set()
        for g in self._gras:
            #print(g.getCurDire())
            if g.getCurDire() == dire:
                temp = g.copy()
                # print('方向为%s'%dire)
                # print('需要前进%s'%temp)
                temp.forward()
                # print('前进后%s'%temp)
                # print('')
                gramSet.add(temp)
        #print(statusParam)
        return Status(gramSet,graMap)
    # 获取可规约项目列表
    def getRegs(self):
        res = []
        for g in self._gras:
            if g.isReg():
                res.append(g)
        return res;

    def __hash__(self):
        return hash(str(self))
    # 判断状态是否相等
    def __eq__(self,other):
        if other == None:
            return False
        return self._gras == other._gras
    # 打印状态
    def __str__(self):
        res = ''
        for gra in self._gras:
            res += str(gra)+ '\n'
        return res 

# 打印状态
def printStatus(statuses,gramOrd):
    # print(statuses)
    # print(gramOrd)
    for status in statuses:
        print('状态%s'%(status[1]))
        print('%s'%status[0])
        regItems = status[0].getRegs()#list(map(str,status[0].getRegs()))
        print('规约项为\n')
        for regItem in regItems:
            print('%s-%s'%(regItem,gramOrd[regItem.getOriGram()]))
        print('')
# 将状态写入文件
def writeToFile(gramList,statusList,gramOrd,move,follows,filename='xtzdj.csv'):
    # print(move)
    statusMap = {}
    # 设置状态-状态数字映射
    for status in statusList:
        statusMap[status[0]] = status[1];

    titles = getAllSymble(gramList)
    # 整理move的格式

    for status in statusList:
        for title in titles:
            # print(move[status[0]])
            # 如果没有项目
            if move[status[0]].get(title) == None:
                # 跳过
                continue;
            # 如果是非终结符
            if title[0] == '<':
                move[status[0]][title] = str(statusMap[move[status[0]][title]])
            # 否则添加一个s
            else:
                move[status[0]][title] = 's' + str(statusMap[move[status[0]][title]])

    # 遍历所有状态，把规约项目调出来
    for status in statusList:
        # 获取所有规约项目
        regItems = status[0].getRegs() 
        # 遍历每一个规约项目
        for reg in regItems:
            if reg.getLeft() == 'S':
                continue
            # 获取需要规约的列名
            rCols = follows[reg.getLeft()]
            # 处理所有列名
            for rCol in rCols:
                # 如果这列还没有东西
                if move[status[0]].get(rCol) == None:
                    # 初始化
                    move[status[0]][rCol] = 'r' + str(gramOrd[reg.getOriGram()]);
                else:
                    move[status[0]][rCol] += ' r' + str(gramOrd[reg.getOriGram()]);
            # !!!
            # move[status[0]]['.'] = 'r' + str(gramOrd[reg.getOriGram()]);
 #       print(move)
    # print(statusList[32][0])
    # print(move[statusList[32][0]])
    # 写入标题行
    with open(filename,'w') as f:
        f.write('')
        for t in titles:
            if t == ',':
                f.write(',逗号');
            else:
                f.write(',%s'%t);
        f.write('\n')
    
        # 写入最终的move
        for status in statusList:
            # 写入状态号
            f.write('%s'%status[1])
            for title in titles:
                # 如果没有项目
                if move[status[0]].get(title) == None:
                    f.write(', ')
                else:
                    f.write(',%s'%move[status[0]][title])
            f.write('\n')

if __name__ == '__main__':
    from grammar import getGras
    l,o,m = getGras()
    s = Status({l[0]},m)
    # s.forward('const')
    # tset = set()
    # tset.add(s.forward('const',m))
    # print(s.forward('const',m) in tset)
    # print(s in tset)
    # print(s.forward('const',m).forward('<常量定义组>',m))

    # 测试规约
    print(list(map(str,s.getRegs())))
    print(list(map(str,s.forward('const',m).getRegs())))
    print(s.forward('const',m).forward('<常量定义组>',m))

    print(list(map(str,s.forward('const',m).forward('<常量定义组>',m).forward(';',m).getRegs())))